/**
  ******************************************************************************
  * @file    FatFs/FatFs_USBDisk/Src/main.c 
  * @author  MCD Application Team
  * @version V1.1.0
  * @date    13-March-2014
  * @brief   Main program body
  *          This sample code shows how to use FatFs with USB disk drive.
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; COPYRIGHT(c) 2014 STMicroelectronics</center></h2>
  *
  * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
  * You may not use this file except in compliance with the License.
  * You may obtain a copy of the License at:
  *
  *        http://www.st.com/software_license_agreement_liberty_v2
  *
  * Unless required by applicable law or agreed to in writing, software 
  * distributed under the License is distributed on an "AS IS" BASIS, 
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  *
  ******************************************************************************
  */

/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "ff_gen_drv.h"
#include "sd_diskio.h"
#include "file_zzp.h"
#include "bsp_sd.h"
#include "f205_flash.h"


#define DEBUG_USB_ENABLE		0

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
FATFS USBDISKFatFs;           /* File system object for USB disk logical drive */
FIL MyFile;                   /* File object */
char USBDISKPath[4];          /* USB Host logical drive path */
__ALIGN_BEGIN	USBH_HandleTypeDef hUSB_Host; 	__ALIGN_END;/* USB Host handle */

__ALIGN_BEGIN	FATFS SDFatFs;  __ALIGN_END;/* File system object for SD card logical drive */
///FIL MyFile;     /* File object */
char SDPath[4]; /* SD card logical drive path */

uint8_t ParamBuf[256];

typedef enum {
  APPLICATION_IDLE = 0,  
  APPLICATION_START,    
  APPLICATION_RUNNING,
}MSC_ApplicationTypeDef;

MSC_ApplicationTypeDef Appli_state = APPLICATION_IDLE;

/* Private function prototypes -----------------------------------------------*/ 
static void SystemClock_Config(void);
static void Error_Handler(void);
static void USBH_UserProcess(USBH_HandleTypeDef *phost, uint8_t id);
static void MSC_Application(void);
void TestSD(void);
void GetParams(void);


APP_INFO AppInfo;
uint8_t RstF = 0;

__IO uint32_t UsbTm = 0;
__IO uint32_t UsbErrTm = 0;
__IO uint32_t DlyTm = 0;



/////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////
///									Functions
/////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////
/**
  * @brief  Main program
  * @param  None
  * @retval None
  */
int main(void)
{
	memset(&AppInfo, 0, sizeof(AppInfo));
	AppInfo.CopyLedFlag = COPY_LED_STATUS_USB;
	
	HAL_Init();
 
	/* Configure the system clock to 120 MHz */
	SystemClock_Config();
	
	GetParams();
		
	BSP_SD_Init();
	
	SetCopyInfo();
	
	if(FATFS_LinkDriver(&SD_Driver, SDPath, DRV_MMC) == 0)
	{
		/*##-2- Register the file system object to the FatFs module ##############*/
		if(f_mount(&SDFatFs, (TCHAR const*)SDPath, 0) != FR_OK)
		{
			/* FatFs Initialization Error */
			Error_Handler();
		}
		else{
			
			///TestSD();			
			UsbTm = 0;
			///ResetULPI();
			while (UsbTm < 200){}
			DeResetULPI();
			UsbTm = 0;
			while (UsbTm < 10){}
			
			/*##-1- Link the USB Host disk I/O driver ##################################*/
			if(FATFS_LinkDriver(&USBH_Driver, USBDISKPath, DRV_USB) == 0)
			{
				/*##-2- Init Host Library ################################################*/
				USBH_Init(&hUSB_Host, USBH_UserProcess, 0);
    
				/*##-3- Add Supported Class ##############################################*/
				USBH_RegisterClass(&hUSB_Host, USBH_MSC_CLASS);
    
				/*##-4- Start Host Process ###############################################*/
				USBH_Start(&hUSB_Host);
				
				UsbTm = 0;
				UsbErrTm = 0;
    
				/*##-5- Run Application (Blocking mode) ##################################*/
				while (1)
				{  
					/* USB Host Background task */
					USBH_Process(&hUSB_Host);
      
					/* Mass Storage Application State Machine */
					switch(Appli_state)
					{
						case APPLICATION_START:
							MSC_Application();
							Appli_state = APPLICATION_IDLE;
							break;
        
						case APPLICATION_IDLE:
						default:
							break;      
					}
					UsbTm = 0;
					if (hUSB_Host.gState != HOST_CLASS){
						
						if (UsbErrTm > 15000)
							RstF = 3;
					}
					else{
						
						if (UsbErrTm > 60000)
							RstF = 4;
					}
				}
			}
		}
	}
  
	/* Infinite loop */
	for(;;);
}

/**
  * @brief  Main routine for Mass Storage Class
  * @param  None
  * @retval None
  */

static void MSC_Application(void)
{
#if (DEBUG_USB_ENABLE==1)
	FRESULT res;                                          /* FatFs function common result code */
	uint32_t byteswritten, bytesread;                     /* File write/read counts */
	uint8_t wtext[] = "This is STM32 working with FatFs"; /* File write buffer */
	uint8_t rtext[100];                                   /* File read buffer */
#endif  
  
	if(f_mount(&USBDISKFatFs, (TCHAR const*)USBDISKPath, 0) != FR_OK)
	{
		Error_Handler();
	}
	else
	{
#if (DEBUG_USB_ENABLE==0)
		CopyUsbFiles();
#else
		if(f_open(&MyFile, "1:STM32.TXT", FA_CREATE_ALWAYS | FA_WRITE) != FR_OK) 
		{
			Error_Handler();
		}
		else
		{
			res = f_write(&MyFile, wtext, sizeof(wtext), (void *)&byteswritten);
      
			if((byteswritten == 0) || (res != FR_OK))
			{
				f_close(&MyFile);
				Error_Handler();
			}
			else
			{
				f_close(&MyFile);
        
				if(f_open(&MyFile, "1:STM32.TXT", FA_READ) != FR_OK)
				{
					Error_Handler();
				}
				else
				{
					res = f_read(&MyFile, rtext, sizeof(rtext), (void *)&bytesread);
          
					if((bytesread == 0) || (res != FR_OK))
					{
						Error_Handler();
					}
					else
					{
						f_close(&MyFile);
            
						if((bytesread != byteswritten))
						{                
							Error_Handler();
						}
						else
						{
							///BSP_LED_On(LED1);
						}
					}
				}
			}

		}
	
		///if (CreateFile()){
		
		///	CopyBigFile();
		///}
#endif 
	}
 
	///FATFS_UnLinkDriver(USBDISKPath);
}

void TestSD(void)
{
	FRESULT res;
	uint32_t byteswritten;
	uint8_t wtext[] = "This is STM32 working with FatFs"; /* File write buffer */
	if(f_open(&MyFile, "0:STM32.TXT", FA_CREATE_ALWAYS | FA_WRITE) != FR_OK) 
    {
      /* 'STM32.TXT' file Open for write Error */
      Error_Handler();
    }
    else
    {
		/* Write data to the text file */
		res = f_write(&MyFile, wtext, sizeof(wtext), (void *)&byteswritten);
		if((byteswritten == 0) || (res != FR_OK))
		  Error_Handler();
	  
		f_close(&MyFile);
	}
}

/**
  * @brief  User Process
  * @param  phost: Host handle
  * @param  id: Host Library user message ID
  * @retval None
  */
static void USBH_UserProcess(USBH_HandleTypeDef *phost, uint8_t id)
{  
  switch(id)
  { 
  case HOST_USER_SELECT_CONFIGURATION:
    break;
    
  case HOST_USER_DISCONNECTION:
    Appli_state = APPLICATION_IDLE;
    f_mount(NULL, (TCHAR const*)"", 0); 
	if (AppInfo.CopyLedFlag == COPY_LED_STATUS_NORMAL)
		UpdateUsbCopyInfo(0x80);
	else
		UpdateUsbCopyInfo(0x89);
	RstF = 2;
    break;
    
  case HOST_USER_CLASS_ACTIVE:
    Appli_state = APPLICATION_START;
    break;
    
  default:
    break; 
  }
}

/**
  * @brief  System Clock Configuration
  *         The system Clock is configured as follow : 
  *            System Clock source            = PLL (HSE)
  *            SYSCLK(Hz)                     = 120000000
  *            HCLK(Hz)                       = 120000000
  *            AHB Prescaler                  = 1
  *            APB1 Prescaler                 = 4
  *            APB2 Prescaler                 = 2
  *            HSE Frequency(Hz)              = 25000000
  *            PLL_M                          = 25
  *            PLL_N                          = 240
  *            PLL_P                          = 2
  *            PLL_Q                          = 5
  *            VDD(V)                         = 3.3
  *            Flash Latency(WS)              = 3
  * @param  None
  * @retval None
  */
static void SystemClock_Config(void)
{
  RCC_ClkInitTypeDef RCC_ClkInitStruct;
  RCC_OscInitTypeDef RCC_OscInitStruct;

  /* Enable HSE Oscillator and activate PLL with HSE as source */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLM = 25;
  RCC_OscInitStruct.PLL.PLLN = 240;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
  RCC_OscInitStruct.PLL.PLLQ = 5;
  HAL_RCC_OscConfig(&RCC_OscInitStruct);
  
  /* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2 
     clocks dividers */
  RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
  HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_3);
}

/**
  * @brief  This function is executed in case of error occurrence.
  * @param  None
  * @retval None
  */
static void Error_Handler(void)
{
  /* Turn LED3 on */
  ///BSP_LED_On(LED3);
  ///while(1)
  {
  }
}

#ifdef USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t* file, uint32_t line)
{ 
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */

  /* Infinite loop */
  while (1)
  {}
}
#endif



void HAL_MspInit(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
  
	/* Enable DOG and ULPI Reset clock */
	__GPIOB_CLK_ENABLE();
	///
	GPIO_InitStructure.Pin = GPIO_PIN_8 | GPIO_PIN_14;
  	GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
	GPIO_InitStructure.Pull = GPIO_PULLUP;
	GPIO_InitStructure.Speed = GPIO_SPEED_FAST;
  	HAL_GPIO_Init(GPIOB, &GPIO_InitStructure); 
	
	ResetULPI();
	
	/* Enable LEDs clock */
	__GPIOF_CLK_ENABLE();
	///LEDs
	GPIO_InitStructure.Pin = GPIO_PIN_6 | GPIO_PIN_7 | GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_11;
  	HAL_GPIO_Init(GPIOF, &GPIO_InitStructure); 
	
	EnableLED(ERR_LED_PIN, 0);
	EnableLED(CFG_LED_PIN, 0);
	EnableLED(TX_LED_PIN, 0);
}


void EnableLED(uint16_t led_pin, uint8_t enable)
{
	if (!enable)
		GPIOF->BSRRL = led_pin;
	else
		GPIOF->BSRRH = led_pin;
}



void UsbMonitor(void)
{
	UsbTm++;
	if (UsbTm > 30000)
		RstF = 1;
}

void FeedDog(void)
{
	if (!RstF)
		GPIOB->ODR ^= GPIO_PIN_8;
}

void ResetULPI(void)
{
	GPIOB->BSRRH = GPIO_PIN_14;
}

void DeResetULPI(void)
{
	GPIOB->BSRRL = GPIO_PIN_14;
}

uint16_t CopyLedTm = 0;
uint16_t WorkLedTm = 0;

void LedHandler(void)
{
	static uint16_t t1 = 0, t2 = 0;
	
	if (AppInfo.CopyLedFlag == COPY_LED_STATUS_NORMAL){
		
		t1 = 20;
		t2 = 40;
	}
	else{
		
		t1 = 100;
		t2 = 300;
	}
	
	if (CopyLedTm < t1)
		GPIOF->BSRRH = COPY_LED_PIN;
	else if (CopyLedTm < t2)
		GPIOF->BSRRL = COPY_LED_PIN;
	else
		CopyLedTm = 0;
	
	if (WorkLedTm < 100)
		GPIOF->BSRRH = WORK_LED_PIN;
	else if (WorkLedTm < 2000)
		GPIOF->BSRRL = WORK_LED_PIN;
	else
		WorkLedTm = 0;
		
	CopyLedTm++;
	WorkLedTm++;
}

extern uint16_t Calc_CRCByte(uint8_t *Buf, uint16_t Len);

void GetParams(void)
{
	uint8_t *p, err = 0;
	uint16_t crc, tmp;
	uint32_t addr;
	
	F205_ReadParams(PARAMS_ADDRESS, &(ParamBuf[0]), 256);
	p = &ParamBuf[160];
	crc = Calc_CRCByte(p, 14);
	tmp = ((uint16_t)p[14] << 8) + p[15];
	if ((crc != tmp) || (p[0] != 0x71) || (p[1] != 0x61) || \
		(p[2] != 0x42) || (p[3] != 0x55) || \
		(p[4] != MAIN_VER) || (p[5] != SUB_VER_1) || \
		(p[6] != 0x20) || (p[7] != SOFT_YEAR) || \
		(p[8] != SOFT_MONTH) || (p[9] != SOFT_DATE)){
		
		p[0] = 0x71;
		p[1] = 0x61;
		p[2] = 0x42;
		p[3] = 0x55;
	
		p[4] = MAIN_VER;
		p[5] = SUB_VER_1;
		p[6] = 0x20;
		p[7] = SOFT_YEAR;
		p[8] = SOFT_MONTH;
		p[9] = SOFT_DATE;
	
		p[10] = 0;
		p[11] = 0;
		p[12] = 0;
		p[13] = 0;
		crc = Calc_CRCByte(p, 14);
		p[14] = crc >> 8;
		p[15] = crc & 0xff;
	
		err = 1;
	}
	
	if (err){
					
		addr = PARAMS_ADDRESS;
		err = F205_WriteParams(addr, &(ParamBuf[0]), 256);
		if (err){
		}
	}
}





/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
